#!/usr/bin/env python3
# -*- coding: utf-8 -*-


from sarena import *
import minimax
import random

class BasicPlayer(Player):

    def __init__(self):
        self.nb_nodes = {} 
        self.time = 0.0
        
    def successors(self, state):
        board, player = state
        actions = board.get_actions() 
        
        # ajouter quelles actions on retourne en premier 
        for action in actions:
            yield action,(board.clone().play_action(action), -player)
        
    def cutoff(self, state, depth, time_left=1200, time_elapsed=0):
        board, player = state
        # Count nb of nodes traversed by depth 
        #if str(depth) not in self.nb_nodes.keys() :
        #    self.nb_nodes[str(depth)] = 1
        #else:
        #    self.nb_nodes[str(depth)] += 1             
        if depth>0:
            return True
        else:
            return False

    def evaluate(self, state):
        board, player = state
        return compute_value2(state)
    

    def play(self, percepts, step, time_left):
        if step % 2 == 0:
            player = -1
        else:
            player = 1
        self.time_left = time_left
        board = Board(percepts)
        state = (board, player)
        #actions = list(board.get_actions())
        #print(len(actions)," actions left on step ",step)
        return minimax.search(state, self)
            
        
    def get_nb_nodes(self):
        return self.nb_nodes.copy()

def compute_value2(state):
    """Return a score for this state.

    The score is the difference between the number of towers of each
    player. In case of ties, it is the difference between the maximal
    height towers of each player. If self.is_finished() returns True,
    this score represents the winner (<0: red, >0: yellow, 0: draw).

Souci : 
- il prefere proteger une tour ennemie que deplacer un bottom adverse a partir d'une case normale

    """
    board, player = state
    score = 0

    for i in range(board.rows):
        for j in range(board.columns):
            tower = board.get_tower(board.m[i][j])

            if tower:
                val_circle = 1
                color_val = 1
                if len(tower)==4:
                    val_circle = 4
                if tower[-1][1] == -player :
                        color_val = 2
            
                if board.m[i][j][0] == 4 : # arrows
                    if tower[-1][1] == 1: # top is yello
                        score += 3*val_circle*len(tower)*color_val 
                    elif tower[-1][1] == -1: #top is red
                        score -= 3*val_circle*len(tower)*color_val 
                
                else: # normal circle
                    
                    if tower[0][0]==-1: # bottom is red
                        if tower[-1][1] == -1: # top is red
                            score -= 3*val_circle*(5-len(tower))*color_val
                        elif tower[-1][1] == 1: # top is yellow
                            if len(tower)==3:
                                score -= 2*val_circle*(5-len(tower))*color_val
                            else:
                                score += 1*val_circle*(5-len(tower))*color_val
                        else: 
                            if len(tower)==3:
                                score -= 1*val_circle*(5-len(tower))*color_val
                            else:
                                score += 1*val_circle*(5-len(tower))*color_val
                            
                    elif tower[0][0] == 1: # bottom yellow
                        if tower[-1][1] == 1: # top is yello
                            score += 3*val_circle*(5-len(tower))*color_val
                        elif tower[-1][1] == -1: #top is red
                            if len(tower)==3:
                                score += 2*val_circle*(5-len(tower))*color_val
                            else:
                                score -= 1*val_circle*(5-len(tower))*color_val
                        else:
                            if len(tower)==3:
                                score += 1*val_circle*(5-len(tower))*color_val
                            else:
                                score -= 1*val_circle*(5-len(tower))*color_val
                    else: # bottom is grey
                        if tower[-1][1] == 1: # top is yello
                            score += val_circle*(5-len(tower))*color_val
                        elif tower[-1][1] == -1: #top is red
                            score -= val_circle*(5-len(tower))*color_val
                            
                        
                        
    if score == 0:
        
        for i in range(board.rows):
            for j in range(board.columns):
                tower = board.get_tower(board.m[i][j])
                if tower:
                    if tower[-1][1] == -1:
                        for half_tok in filter(lambda token:
                                                   (token[0] == -1 or
                                                    token[1] == -1),
                                               tower):
                            score -= 1
                    elif tower[-1][1] == 1:
                        for half_tok in filter(lambda token:
                                                   (token[0] == 1 or
                                                    token[1] == 1),
                                               tower):
                            score += 1
    return score

if __name__ == "__main__":
    player_main(BasicPlayer())













def compute_value____(state):
    "This evaluates the chances to win, returns a interger value "
    board = Board()
    board, player = state
    actions = list(board.get_actions())
    if player==-1: m = board.get_percepts(True)
    else:          m = board.m   
    val = 0
    for action in actions:
        tower_src = m[action[0]][action[1]]
        tower_dest = m[action[2]][action[3]]
        height_total = board.get_height(tower_src) + board.get_height(tower_dest)
        #--------------------   move from a circle with arrows   ------------------------
        
        if move_from_arrow(board,action): # move from a circle with arrows
            
            #----- Move on a tower(destination) having my color on bottom (*2)--------------------
            if is_my_color(state, action[2], action[3], 0): 
                #--- my color is on top on source tower
                if is_my_color(state,action[0],action[1]): 
                    val += 2*height_total
                #--- opponent color on top on source tower-----
                elif is_opponent_color(state,action[0], action[1]): 
                    val += 2*3*height_total
                #--- gray color on top on source tower -----
                else: 
                    val += 2*2*height_total
            #----- Move on a tower(destination) having opponent color on bottom (*3)-----------------       
            elif is_opponent_color(state, action[2], action[3], 0):   
                #--- my color on top of source tower -----
                if is_my_color(state,action[0], action[1]):
                    val = val - 3*3*height_total
                #--- opponent color on top of source tower -----
                elif is_opponent_color(state, action[0], action[1]): 
                    val = val - 3*1*height_total
                #--- gray color on top of source tower -----
                else:
                    val = val - 3*2*height_total
                #val = val -3
            #----- Move on a tower having gray color on bottom  (*1)--------------------
            else: 
                
                #--- my color on top of source tower -----
                if is_my_color(state,action[0], action[1]):
                    val_src_top = 3
                    #--- my color on top of dest tower
                    if is_my_color(state, action[2], action[3]): 
                        val = val + val_src_top*1*height_total
                    #--- opponent color on top of dest tower (3)---
                    elif is_opponent_color(state, action[2], action[3]):
                        val = val + val_src_top*3*height_total
                    #--- gray color on top of dest tower (2)---
                    else :
                        val = val + val_src_top*2*height_total                    
                    
                #--- opponent color on top of source tower -----
                elif is_opponent_color(state, action[0], action[1]): 
                    val_src_top = 3
                    #--- my color on top of dest tower
                    if is_my_color(state, action[2], action[3]): 
                        val = val - val_src_top*3*height_total
                    #--- opponent color on top of dest tower (3)---
                    elif is_opponent_color(state, action[2], action[3]):
                        val = val - val_src_top*1*height_total
                    #--- gray color on top of dest tower (2)---
                    else :
                        val = val - val_src_top*2*height_total  
                #--- gray color on top of source tower -----
                else: # ==== no difference
                    val_src_top = 2
                    #--- my color on top of dest tower
                    if is_my_color(state, action[2], action[3]): 
                        val = val - val_src_top*3*height_total
                    #--- opponent color on top of dest tower (3)---
                    elif is_opponent_color(state, action[2], action[3]):
                        val = val + val_src_top*3*height_total
                    #--- gray color on top of dest tower (2)---
                    else :
                        val = val - val_src_top*2*height_total  
                
                
        # ----------  move from a normal circle on a circle with arrows   ------------------- 
        else: 

            # -------  destination circle (with arrows) is empty   -------------------------- 
            
            if board.get_height(tower_dest)==0: # no pawn on destination circle
                if is_opponent_color(state, action[0], action[1], 0): # opp. color on bottom
                    val = val - 3*(4-board.get_height(tower_src)) 
                   
                   
                    
            #------- destination circle (with arrows)  is not empty --------------------------
            else: 
                
                #----- Move a tower(source) having my color on top (*3)-----------------
                if is_my_color(state, action[0], action[1]): 
                    val_src_top = 3
                    #--- my color is on top on destination tower (*1 pos)----
                    if is_my_color(state,action[2],action[3]): 
                        val_dest_top = 1
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val + val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val + val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val + val_src_top*val_dest_top*2*height_total
                    
                    #--- opponent color on top on destination tower (*3 pos)-----
                    elif is_opponent_color(state,action[2], action[3]): 
                        val_dest_top = 3
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val + val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val + val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val + val_src_top*val_dest_top*2*height_total
                    
                    #--- gray color on top on destination tower (*2)-----
                    else: 
                        val_dest_top = 2
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val + val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val + val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val + val_src_top*val_dest_top*2*height_total


                #----- Move a tower(source) having opponent color on top (*1 )--------       
                elif is_opponent_color(state, action[0], action[1]):   
                    val_src_top = 3 #beacause it's a negative action
                    #--- my color is on top on destination tower (*3 neg)----
                    if is_my_color(state,action[2],action[3]): 
                        val_dest_top = 3 # because it's negative action
                        #--- my color bottom on src (3)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val - val_src_top*val_dest_top*3*height_total
                        #--- opponent color on bottom on src (1)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val - val_src_top*val_dest_top*1*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val - val_src_top*val_dest_top*2*height_total
                    
                    #--- opponent color on top on destination tower (*3 pos)-----
                    elif is_opponent_color(state,action[2], action[3]): 
                        val_dest_top = 1 # cause negative action, 3 otherwise
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val - val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val - val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val - val_src_top*val_dest_top*2*height_total
                    
                    #--- gray color on top on destination tower (*2)-----
                    else: 
                        val_dest_top = 2
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val - val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val - val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val - val_src_top*val_dest_top*2*height_total
                        
                #----- Move a tower having gray color on top (*2)  -----------
                else:
                    val_src_top = 2
                    #--- my color is on top on destination tower (*1 pos)----
                    if is_my_color(state,action[2],action[3]): 
                        val_dest_top = 3
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val - val_src_top*val_dest_top*3*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val - val_src_top*val_dest_top*1*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val - val_src_top*val_dest_top*2*height_total
                    
                    #--- opponent color on top on destination tower (*3 pos)-----
                    elif is_opponent_color(state,action[2], action[3]): 
                        val_dest_top = 3
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val + val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val + val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val + val_src_top*val_dest_top*2*height_total
                    
                    #--- gray color on top on destination tower (*2)-----
                    else: 
                        val_dest_top = 2
                        #--- my color bottom on src (1)---
                        if is_my_color(state, action[0], action[1], 0): 
                            val = val + val_src_top*val_dest_top*1*height_total
                        #--- opponent color on bottom on src (3)---
                        elif is_opponent_color(state, action[0], action[1], 0):
                            val = val + val_src_top*val_dest_top*3*height_total
                        #--- gray color on bottom on src (2)---
                        else :
                            val = val + val_src_top*val_dest_top*2*height_total
                    
                
    return val

def move_from_arrow(board,action):
    return board.m[action[0]][action[1]][0]==4

def is_my_color(state, i, j, top=1):
    "True if the color of player is on top on ith line and jth column on the board"
    board , player = state
    if player==-1: m = board.get_percepts(True)
    else:          m = board.m
    tower = m[i][j]
    if top==1 : 
        return tower[board.get_height(tower)][top]==player
    else:
        return tower[1][top]==player 

def is_opponent_color(state,i,j, top=1):
    board , player = state
    if player==-1: m = board.get_percepts(True)
    else:          m = board.m
    tower = m[i][j]
    if top==1 :
        return tower[board.get_height(tower)][top]!=player and \
tower[board.get_height(tower)][top]!=2  # different from me and gray
    else :
        return tower[1][top]!=player and tower[1][top]!=2  # different from me and gray        

